#include <search.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
#include "common.h"

struct TVTS_DLL_ENTRY {
	char* data;
	LIST_ENTRY(TVTS_DLL_ENTRY) entries;
};

LIST_HEAD(TVTS_DLL_HEAD, TVTS_DLL_ENTRY);

int main(int argc, char* argv[]) {
	char buf[MAXLINE];

	// SLL
	struct TVTS_DLL_ENTRY *np = 0, *n1 = 0, *n2 = 0;
	struct TVTS_DLL_HEAD head;
	LIST_INIT(&head);

	// init
	if(!hcreate(100)) {
		fprintf(stderr, "%s\n", "Cannot create the hashtable!");
	} else {
		printf("%s\n", "Hashtable created.");
	}

	// check and insert
	int i, first = 1;
	for (i = 1; i < argc; i ++) {
		char* arg = argv[i];
		snprintf(buf, MAXLINE, "%s-%d-%s", arg, i, arg);
		ENTRY item;
		item.key = cp_str(arg);
		ENTRY *entry = hsearch(item, FIND);
		printf("> %d:\n", i);
		if (!entry) {
			item.data = (void*)cp_str(buf);
			if (!hsearch(item, ENTER)) {
				fprintf(stderr, "Cannot insert %s as %s!\n", arg, buf);
			} else {
				printf("Inserted %s as %s.\n", arg, buf);
				np = (struct TVTS_DLL_ENTRY *)malloc(sizeof(struct TVTS_DLL_ENTRY));
				np->data = cp_str(arg);

				n2 = np;
				if (first) {
					first = 0;
					LIST_INSERT_HEAD(&head, n2, entries);
				} else {
					LIST_INSERT_AFTER(n1, n2, entries);
				}
				n1 = np;
			}
		} else {
			printf("Updating %s from %s to %s.\n", arg, (char*)entry->data, buf);
			free(entry->data);
			entry->data = (void*)cp_str(buf);
		}
	}
	printf("Insertions done.\n");

	// iterate
	printf("Start iteration ...\n");
	i = 0;
	LIST_FOREACH(np, &head, entries) {
    	printf("%d: %s\n", ++i, np->data);
    	ENTRY the_entry;
    	the_entry.key = np->data;
		ENTRY *entry = hsearch(the_entry, FIND);
    	if (!entry) {
    		fprintf(stderr, "Cannot found %s!\n", np->data);
    	} else {
    		printf("%s => %s\n", np->data, (char*)entry->data);
    	}
	}
	printf("Iteration done.\n");

	// destruct
	printf("Cleaning ...\n");
	i = 0;
	LIST_FOREACH(np, &head, entries) {
		printf("Deleting: %d: %s\n", ++i, np->data);
		ENTRY the_entry;
		the_entry.key = np->data;
		ENTRY *entry = hsearch(the_entry, FIND);
		if (!entry) {
			fprintf(stderr, "Cannot found %s!\n", np->data);
		} else {
			printf("Found, Deleting: %s => %s\n", np->data, (char*)entry->data);
			free(entry->key);
			free(entry->data);
			printf("Deleted.\n");
		}
	}
	hdestroy();
	printf("Htab deleted.");

	n1 = LIST_FIRST(&head);
	while (n1 != NULL) {
		n2 = LIST_NEXT(n1, entries);
		free(n1->data);
		free(n1);
		n1 = n2;
	}
    LIST_INIT(&head);
    printf("Cleaning done.\n");
}
